home *** CD-ROM | disk | FTP | other *** search
- Subject: v09i041: MicroEMACS, version 3.8b, Part09/14
- Newsgroups: mod.sources
- Approved: rs@mirror.TMC.COM
-
- Submitted by: ihnp4!itivax!duncan!lawrence (Daniel Lawrence)
- Mod.sources: Volume 9, Issue 41
- Archive-name: uemacs3.8b/Part09
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If this archive is complete, you will see the message:
- # "End of archive 9 (of 14)."
- # Contents: file.c isearch.c
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo shar: Extracting \"file.c\" \(18229 characters\)
- if test -f file.c ; then
- echo shar: Will not over-write existing file \"file.c\"
- else
- sed "s/^X//" >file.c <<'END_OF_file.c'
- X/* FILE.C: for MicroEMACS
- X
- X The routines in this file handle the reading, writing
- X and lookup of disk files. All of details about the
- X reading and writing of the disk are in "fileio.c".
- X
- X*/
- X
- X#include <stdio.h>
- X#include "estruct.h"
- X#include "edef.h"
- X
- X#if MEGAMAX
- Xoverlay "file"
- X#endif
- X
- X/*
- X * Read a file into the current
- X * buffer. This is really easy; all you do it
- X * find the name of the file, and call the standard
- X * "read a file into the current buffer" code.
- X * Bound to "C-X C-R".
- X */
- Xfileread(f, n)
- X{
- X register int s;
- X char fname[NFILEN];
- X
- X if (restflag) /* don't allow this command if restricted */
- X return(resterr());
- X if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
- X return(s);
- X return(readin(fname, TRUE));
- X}
- X
- X/*
- X * Insert a file into the current
- X * buffer. This is really easy; all you do it
- X * find the name of the file, and call the standard
- X * "insert a file into the current buffer" code.
- X * Bound to "C-X C-I".
- X */
- Xinsfile(f, n)
- X{
- X register int s;
- X char fname[NFILEN];
- X
- X if (restflag) /* don't allow this command if restricted */
- X return(resterr());
- X if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- X return(rdonly()); /* we are in read only mode */
- X if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
- X return(s);
- X return(ifile(fname));
- X}
- X
- X/*
- X * Select a file for editing.
- X * Look around to see if you can find the
- X * fine in another buffer; if you can find it
- X * just switch to the buffer. If you cannot find
- X * the file, create a new buffer, read in the
- X * text, and switch to the new buffer.
- X * Bound to C-X C-F.
- X */
- Xfilefind(f, n)
- X{
- X char fname[NFILEN]; /* file user wishes to find */
- X register int s; /* status return */
- X
- X if (restflag) /* don't allow this command if restricted */
- X return(resterr());
- X if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
- X return(s);
- X return(getfile(fname, TRUE));
- X}
- X
- Xviewfile(f, n) /* visit a file in VIEW mode */
- X{
- X char fname[NFILEN]; /* file user wishes to find */
- X register int s; /* status return */
- X register WINDOW *wp; /* scan for windows that need updating */
- X
- X if (restflag) /* don't allow this command if restricted */
- X return(resterr());
- X if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
- X return (s);
- X s = getfile(fname, FALSE);
- X if (s) { /* if we succeed, put it in view mode */
- X curwp->w_bufp->b_mode |= MDVIEW;
- X
- X /* scan through and update mode lines of all windows */
- X wp = wheadp;
- X while (wp != NULL) {
- X wp->w_flag |= WFMODE;
- X wp = wp->w_wndp;
- X }
- X }
- X return(s);
- X}
- X
- X#if CRYPT
- Xresetkey() /* reset the encryption key if needed */
- X
- X{
- X register int s; /* return status */
- X
- X /* turn off the encryption flag */
- X cryptflag = FALSE;
- X
- X /* if we are in crypt mode */
- X if (curbp->b_mode & MDCRYPT) {
- X if (curbp->b_key[0] == 0) {
- X s = setkey(FALSE, 0);
- X if (s != TRUE)
- X return(s);
- X }
- X
- X /* let others know... */
- X cryptflag = TRUE;
- X
- X /* and set up the key to be used! */
- X /* de-encrypt it */
- X crypt((char *)NULL, 0);
- X crypt(curbp->b_key, strlen(curbp->b_key));
- X
- X /* re-encrypt it...seeding it to start */
- X crypt((char *)NULL, 0);
- X crypt(curbp->b_key, strlen(curbp->b_key));
- X }
- X
- X return(TRUE);
- X}
- X#endif
- X
- Xgetfile(fname, lockfl)
- X
- Xchar fname[]; /* file name to find */
- Xint lockfl; /* check the file for locks? */
- X
- X{
- X register BUFFER *bp;
- X register LINE *lp;
- X register int i;
- X register int s;
- X char bname[NBUFN]; /* buffer name to put file */
- X
- X for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
- X if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
- X swbuffer(bp);
- X lp = curwp->w_dotp;
- X i = curwp->w_ntrows/2;
- X while (i-- && lback(lp)!=curbp->b_linep)
- X lp = lback(lp);
- X curwp->w_linep = lp;
- X curwp->w_flag |= WFMODE|WFHARD;
- X mlwrite("[Old buffer]");
- X return (TRUE);
- X }
- X }
- X makename(bname, fname); /* New buffer name. */
- X while ((bp=bfind(bname, FALSE, 0)) != NULL) {
- X s = mlreply("Buffer name: ", bname, NBUFN);
- X if (s == ABORT) /* ^G to just quit */
- X return (s);
- X if (s == FALSE) { /* CR to clobber it */
- X makename(bname, fname);
- X break;
- X }
- X }
- X if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
- X mlwrite("Cannot create buffer");
- X return (FALSE);
- X }
- X if (--curbp->b_nwnd == 0) { /* Undisplay. */
- X curbp->b_dotp = curwp->w_dotp;
- X curbp->b_doto = curwp->w_doto;
- X curbp->b_markp = curwp->w_markp;
- X curbp->b_marko = curwp->w_marko;
- X }
- X curbp = bp; /* Switch to it. */
- X curwp->w_bufp = bp;
- X curbp->b_nwnd++;
- X return(readin(fname, lockfl)); /* Read it in. */
- X}
- X
- X/*
- X * Read file "fname" into the current
- X * buffer, blowing away any text found there. Called
- X * by both the read and find commands. Return the final
- X * status of the read. Also called by the mainline,
- X * to read in a file specified on the command line as
- X * an argument. If the filename ends in a ".c", CMODE is
- X * set for the current buffer.
- X */
- Xreadin(fname, lockfl)
- X
- Xchar fname[]; /* name of file to read */
- Xint lockfl; /* check for file locks? */
- X
- X{
- X register LINE *lp1;
- X register LINE *lp2;
- X register int i;
- X register WINDOW *wp;
- X register BUFFER *bp;
- X register int s;
- X register int nbytes;
- X register int nline;
- X register char *sptr; /* pointer into filename string */
- X int lflag; /* any lines longer than allowed? */
- X char line[NLINE];
- X
- X#if FILOCK
- X if (lockfl && lockchk(fname) == ABORT)
- X return(ABORT);
- X#endif
- X#if CRYPT
- X s = resetkey();
- X if (s != TRUE)
- X return(s);
- X#endif
- X bp = curbp; /* Cheap. */
- X if ((s=bclear(bp)) != TRUE) /* Might be old. */
- X return (s);
- X bp->b_flag &= ~(BFINVS|BFCHG);
- X#if ACMODE
- X if (strlen(fname) > 1) { /* check if a 'C' file */
- X sptr = fname + strlen(fname) - 2;
- X if (*sptr == '.' &&
- X (*(sptr + 1) == 'c' || *(sptr + 1) == 'h'))
- X bp->b_mode |= MDCMOD;
- X }
- X#endif
- X strcpy(bp->b_fname, fname);
- X
- X /* turn off ALL keyboard translation in case we get a dos error */
- X TTkclose();
- X
- X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
- X goto out;
- X if (s == FIOFNF) { /* File not found. */
- X mlwrite("[New file]");
- X goto out;
- X }
- X mlwrite("[Reading file]");
- X nline = 0;
- X lflag = FALSE;
- X while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG
- X || s == FIOFUN) {
- X if (s == FIOLNG) {
- X lflag = TRUE;
- X --nline;
- X }
- X nbytes = strlen(line);
- X if ((lp1=lalloc(nbytes)) == NULL) {
- X s = FIOERR; /* Keep message on the */
- X break; /* display. */
- X }
- X lp2 = lback(curbp->b_linep);
- X lp2->l_fp = lp1;
- X lp1->l_fp = curbp->b_linep;
- X lp1->l_bp = lp2;
- X curbp->b_linep->l_bp = lp1;
- X for (i=0; i<nbytes; ++i)
- X lputc(lp1, i, line[i]);
- X ++nline;
- X if (s == FIOFUN)
- X break;
- X }
- X ffclose(); /* Ignore errors. */
- X strcpy(line, "[");
- X if (lflag)
- X strcat(line, "Long lines wrapped, ");
- X if (s == FIOFUN)
- X strcat(line, "Funny line at EOF, ");
- X if (s == FIOEOF || s == FIOFUN) { /* Don't zap message! */
- X sprintf(&line[strlen(line)], "Read %d line", nline);
- X if (nline > 1)
- X strcat(line, "s");
- X strcat(line, "]");
- X }
- X if (s != FIOERR)
- X mlwrite(line);
- X
- Xout:
- X TTkopen(); /* open the keyboard again */
- X for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
- X if (wp->w_bufp == curbp) {
- X wp->w_linep = lforw(curbp->b_linep);
- X wp->w_dotp = lforw(curbp->b_linep);
- X wp->w_doto = 0;
- X wp->w_markp = NULL;
- X wp->w_marko = 0;
- X wp->w_flag |= WFMODE|WFHARD;
- X }
- X }
- X if (s == FIOERR || s == FIOFNF) /* False if error. */
- X return(FALSE);
- X return (TRUE);
- X}
- X
- X/*
- X * Take a file name, and from it
- X * fabricate a buffer name. This routine knows
- X * about the syntax of file names on the target system.
- X * I suppose that this information could be put in
- X * a better place than a line of code.
- X */
- Xmakename(bname, fname)
- Xchar bname[];
- Xchar fname[];
- X{
- X register char *cp1;
- X register char *cp2;
- X
- X cp1 = &fname[0];
- X while (*cp1 != 0)
- X ++cp1;
- X
- X#if AMIGA
- X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
- X --cp1;
- X#endif
- X#if VMS
- X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
- X --cp1;
- X#endif
- X#if CPM
- X while (cp1!=&fname[0] && cp1[-1]!=':')
- X --cp1;
- X#endif
- X#if MSDOS
- X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
- X --cp1;
- X#endif
- X#if FINDER
- X while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
- X --cp1;
- X#endif
- X#if V7 | USG | BSD
- X while (cp1!=&fname[0] && cp1[-1]!='/')
- X --cp1;
- X#endif
- X cp2 = &bname[0];
- X while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
- X *cp2++ = *cp1++;
- X *cp2 = 0;
- X}
- X
- X/*
- X * Ask for a file name, and write the
- X * contents of the current buffer to that file.
- X * Update the remembered file name and clear the
- X * buffer changed flag. This handling of file names
- X * is different from the earlier versions, and
- X * is more compatable with Gosling EMACS than
- X * with ITS EMACS. Bound to "C-X C-W".
- X */
- Xfilewrite(f, n)
- X{
- X register WINDOW *wp;
- X register int s;
- X char fname[NFILEN];
- X
- X if (restflag) /* don't allow this command if restricted */
- X return(resterr());
- X if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
- X return (s);
- X if ((s=writeout(fname)) == TRUE) {
- X strcpy(curbp->b_fname, fname);
- X curbp->b_flag &= ~BFCHG;
- X wp = wheadp; /* Update mode lines. */
- X while (wp != NULL) {
- X if (wp->w_bufp == curbp)
- X wp->w_flag |= WFMODE;
- X wp = wp->w_wndp;
- X }
- X }
- X return (s);
- X}
- X
- X/*
- X * Save the contents of the current
- X * buffer in its associatd file. No nothing
- X * if nothing has changed (this may be a bug, not a
- X * feature). Error if there is no remembered file
- X * name for the buffer. Bound to "C-X C-S". May
- X * get called by "C-Z".
- X */
- Xfilesave(f, n)
- X{
- X register WINDOW *wp;
- X register int s;
- X
- X if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- X return(rdonly()); /* we are in read only mode */
- X if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */
- X return (TRUE);
- X if (curbp->b_fname[0] == 0) { /* Must have a name. */
- X mlwrite("No file name");
- X return (FALSE);
- X }
- X if ((s=writeout(curbp->b_fname)) == TRUE) {
- X curbp->b_flag &= ~BFCHG;
- X wp = wheadp; /* Update mode lines. */
- X while (wp != NULL) {
- X if (wp->w_bufp == curbp)
- X wp->w_flag |= WFMODE;
- X wp = wp->w_wndp;
- X }
- X }
- X return (s);
- X}
- X
- X/*
- X * This function performs the details of file
- X * writing. Uses the file management routines in the
- X * "fileio.c" package. The number of lines written is
- X * displayed. Sadly, it looks inside a LINE; provide
- X * a macro for this. Most of the grief is error
- X * checking of some sort.
- X */
- Xwriteout(fn)
- Xchar *fn;
- X{
- X register int s;
- X register LINE *lp;
- X register int nline;
- X
- X#if CRYPT
- X s = resetkey();
- X if (s != TRUE)
- X return(s);
- X#endif
- X /* turn off ALL keyboard translation in case we get a dos error */
- X TTkclose();
- X
- X if ((s=ffwopen(fn)) != FIOSUC) { /* Open writes message. */
- X TTkopen();
- X return (FALSE);
- X }
- X mlwrite("[Writing..]"); /* tell us were writing */
- X lp = lforw(curbp->b_linep); /* First line. */
- X nline = 0; /* Number of lines. */
- X while (lp != curbp->b_linep) {
- X if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
- X break;
- X ++nline;
- X lp = lforw(lp);
- X }
- X if (s == FIOSUC) { /* No write error. */
- X s = ffclose();
- X if (s == FIOSUC) { /* No close error. */
- X if (nline == 1)
- X mlwrite("[Wrote 1 line]");
- X else
- X mlwrite("[Wrote %d lines]", nline);
- X }
- X } else /* Ignore close error */
- X ffclose(); /* if a write error. */
- X TTkopen();
- X if (s != FIOSUC) /* Some sort of error. */
- X return (FALSE);
- X return (TRUE);
- X}
- X
- X/*
- X * The command allows the user
- X * to modify the file name associated with
- X * the current buffer. It is like the "f" command
- X * in UNIX "ed". The operation is simple; just zap
- X * the name in the BUFFER structure, and mark the windows
- X * as needing an update. You can type a blank line at the
- X * prompt if you wish.
- X */
- Xfilename(f, n)
- X{
- X register WINDOW *wp;
- X register int s;
- X char fname[NFILEN];
- X
- X if (restflag) /* don't allow this command if restricted */
- X return(resterr());
- X if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
- X return (s);
- X if (s == FALSE)
- X strcpy(curbp->b_fname, "");
- X else
- X strcpy(curbp->b_fname, fname);
- X wp = wheadp; /* Update mode lines. */
- X while (wp != NULL) {
- X if (wp->w_bufp == curbp)
- X wp->w_flag |= WFMODE;
- X wp = wp->w_wndp;
- X }
- X curbp->b_mode &= ~MDVIEW; /* no longer read only mode */
- X return (TRUE);
- X}
- X
- X/*
- X * Insert file "fname" into the current
- X * buffer, Called by insert file command. Return the final
- X * status of the read.
- X */
- Xifile(fname)
- Xchar fname[];
- X{
- X register LINE *lp0;
- X register LINE *lp1;
- X register LINE *lp2;
- X register int i;
- X register BUFFER *bp;
- X register int s;
- X register int nbytes;
- X register int nline;
- X int lflag; /* any lines longer than allowed? */
- X char line[NLINE];
- X
- X bp = curbp; /* Cheap. */
- X bp->b_flag |= BFCHG; /* we have changed */
- X bp->b_flag &= ~BFINVS; /* and are not temporary*/
- X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
- X goto out;
- X if (s == FIOFNF) { /* File not found. */
- X mlwrite("[No such file]");
- X return(FALSE);
- X }
- X mlwrite("[Inserting file]");
- X
- X#if CRYPT
- X s = resetkey();
- X if (s != TRUE)
- X return(s);
- X#endif
- X /* back up a line and save the mark here */
- X curwp->w_dotp = lback(curwp->w_dotp);
- X curwp->w_doto = 0;
- X curwp->w_markp = curwp->w_dotp;
- X curwp->w_marko = 0;
- X
- X nline = 0;
- X lflag = FALSE;
- X while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG
- X || s == FIOFUN) {
- X if (s == FIOLNG) {
- X lflag = TRUE;
- X --nline;
- X }
- X nbytes = strlen(line);
- X if ((lp1=lalloc(nbytes)) == NULL) {
- X s = FIOERR; /* Keep message on the */
- X break; /* display. */
- X }
- X lp0 = curwp->w_dotp; /* line previous to insert */
- X lp2 = lp0->l_fp; /* line after insert */
- X
- X /* re-link new line between lp0 and lp2 */
- X lp2->l_bp = lp1;
- X lp0->l_fp = lp1;
- X lp1->l_bp = lp0;
- X lp1->l_fp = lp2;
- X
- X /* and advance and write out the current line */
- X curwp->w_dotp = lp1;
- X for (i=0; i<nbytes; ++i)
- X lputc(lp1, i, line[i]);
- X ++nline;
- X if (s == FIOFUN)
- X break;
- X }
- X ffclose(); /* Ignore errors. */
- X curwp->w_markp = lforw(curwp->w_markp);
- X strcpy(line, "[");
- X if (lflag)
- X strcat(line, "Long lines wrapped, ");
- X if (s == FIOFUN)
- X strcat(line, "Funny line at EOF, ");
- X if (s == FIOEOF || s == FIOFUN) { /* Don't zap message! */
- X sprintf(&line[strlen(line)], "Inserted %d line", nline);
- X if (nline > 1)
- X strcat(line, "s");
- X strcat(line, "]");
- X }
- X if (s != FIOERR)
- X mlwrite(line);
- Xout:
- X /* advance to the next line and mark the window for changes */
- X curwp->w_dotp = lforw(curwp->w_dotp);
- X curwp->w_flag |= WFHARD | WFMODE;
- X
- X /* copy window parameters back to the buffer structure */
- X curbp->b_dotp = curwp->w_dotp;
- X curbp->b_doto = curwp->w_doto;
- X curbp->b_markp = curwp->w_markp;
- X curbp->b_marko = curwp->w_marko;
- X
- X if (s == FIOERR) /* False if error. */
- X return (FALSE);
- X return (TRUE);
- X}
- END_OF_file.c
- if test 18229 -ne `wc -c <file.c`; then
- echo shar: \"file.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"isearch.c\" \(18764 characters\)
- if test -f isearch.c ; then
- echo shar: Will not over-write existing file \"isearch.c\"
- else
- sed "s/^X//" >isearch.c <<'END_OF_isearch.c'
- X/*
- X * The functions in this file implement commands that perform incremental
- X * searches in the forward and backward directions. This "ISearch" command
- X * is intended to emulate the same command from the original EMACS
- X * implementation (ITS). Contains references to routines internal to
- X * SEARCH.C.
- X *
- X * REVISION HISTORY:
- X *
- X * D. R. Banks 9-May-86
- X * - added ITS EMACSlike ISearch
- X *
- X * John M. Gamble 5-Oct-86
- X * - Made iterative search use search.c's scanner() routine.
- X * This allowed the elimination of bakscan().
- X * - Put isearch constants into esearch.h
- X * - Eliminated the passing of 'status' to scanmore() and
- X * checknext(), since there were no circumstances where
- X * it ever equalled FALSE.
- X */
- X
- X#include <stdio.h>
- X#include "estruct.h"
- X#include "edef.h"
- X#include "esearch.h"
- X
- X#if ISRCH
- X
- Xextern int scanner(); /* Handy search routine */
- Xextern int eq(); /* Compare chars, match case */
- Xextern char tap[]; /* Reverse pattern array.*/
- X/* A couple of "own" variables for re-eat */
- X
- Xint (*saved_get_char)(); /* Get character routine */
- Xint eaten_char = -1; /* Re-eaten char */
- X
- X/* A couple more "own" variables for the command string */
- X
- Xint cmd_buff[CMDBUFLEN]; /* Save the command args here */
- Xint cmd_offset; /* Current offset into command buff */
- Xint cmd_reexecute = -1; /* > 0 if re-executing command */
- X
- X
- X/*
- X * Subroutine to do incremental reverse search. It actually uses the
- X * same code as the normal incremental search, as both can go both ways.
- X */
- X
- Xint risearch(f, n)
- X{
- X LINE *curline; /* Current line on entry */
- X int curoff; /* Current offset on entry */
- X
- X /* remember the initial . on entry: */
- X
- X curline = curwp->w_dotp; /* Save the current line pointer */
- X curoff = curwp->w_doto; /* Save the current offset */
- X
- X /* Make sure the search doesn't match where we already are: */
- X
- X backchar(TRUE, 1); /* Back up a character */
- X
- X if (!(isearch(f, -n))) /* Call ISearch backwards */
- X { /* If error in search: */
- X curwp->w_dotp = curline; /* Reset the line pointer */
- X curwp->w_doto = curoff; /* and the offset to original value */
- X curwp->w_flag |= WFMOVE; /* Say we've moved */
- X update(FALSE); /* And force an update */
- X mlwrite ("[search failed]"); /* Say we died */
- X } else mlerase (); /* If happy, just erase the cmd line */
- X}
- X
- X/* Again, but for the forward direction */
- X
- Xint fisearch(f, n)
- X{
- X LINE *curline; /* Current line on entry */
- X int curoff; /* Current offset on entry */
- X
- X /* remember the initial . on entry: */
- X
- X curline = curwp->w_dotp; /* Save the current line pointer */
- X curoff = curwp->w_doto; /* Save the current offset */
- X
- X /* do the search */
- X
- X if (!(isearch(f, n))) /* Call ISearch forwards */
- X { /* If error in search: */
- X curwp->w_dotp = curline; /* Reset the line pointer */
- X curwp->w_doto = curoff; /* and the offset to original value */
- X curwp->w_flag |= WFMOVE; /* Say we've moved */
- X update(FALSE); /* And force an update */
- X mlwrite ("[search failed]"); /* Say we died */
- X } else mlerase (); /* If happy, just erase the cmd line */
- X}
- X
- X/*
- X * Subroutine to do an incremental search. In general, this works similarly
- X * to the older micro-emacs search function, except that the search happens
- X * as each character is typed, with the screen and cursor updated with each
- X * new search character.
- X *
- X * While searching forward, each successive character will leave the cursor
- X * at the end of the entire matched string. Typing a Control-S or Control-X
- X * will cause the next occurrence of the string to be searched for (where the
- X * next occurrence does NOT overlap the current occurrence). A Control-R will
- X * change to a backwards search, META will terminate the search and Control-G
- X * will abort the search. Rubout will back up to the previous match of the
- X * string, or if the starting point is reached first, it will delete the
- X * last character from the search string.
- X *
- X * While searching backward, each successive character will leave the cursor
- X * at the beginning of the matched string. Typing a Control-R will search
- X * backward for the next occurrence of the string. Control-S or Control-X
- X * will revert the search to the forward direction. In general, the reverse
- X * incremental search is just like the forward incremental search inverted.
- X *
- X * In all cases, if the search fails, the user will be feeped, and the search
- X * will stall until the pattern string is edited back into something that
- X * exists (or until the search is aborted).
- X */
- X
- Xisearch(f, n)
- X{
- X int status; /* Search status */
- X int col; /* prompt column */
- X register int cpos; /* character number in search string */
- X register int c; /* current input character */
- X register int expc; /* function expanded input char */
- X char pat_save[NPAT]; /* Saved copy of the old pattern str */
- X LINE *curline; /* Current line on entry */
- X int curoff; /* Current offset on entry */
- X int init_direction; /* The initial search direction */
- X
- X /* Initialize starting conditions */
- X
- X cmd_reexecute = -1; /* We're not re-executing (yet?) */
- X cmd_offset = 0; /* Start at the beginning of the buff */
- X cmd_buff[0] = '\0'; /* Init the command buffer */
- X strncpy (pat_save, pat, NPAT); /* Save the old pattern string */
- X curline = curwp->w_dotp; /* Save the current line pointer */
- X curoff = curwp->w_doto; /* Save the current offset */
- X init_direction = n; /* Save the initial search direction */
- X
- X /* This is a good place to start a re-execution: */
- X
- Xstart_over:
- X
- X /* ask the user for the text of a pattern */
- X col = promptpattern("ISearch: "); /* Prompt, remember the col */
- X
- X cpos = 0; /* Start afresh */
- X status = TRUE; /* Assume everything's cool */
- X
- X /*
- X Get the first character in the pattern. If we get an initial Control-S
- X or Control-R, re-use the old search string and find the first occurrence
- X */
- X
- X c = ectoc(expc = get_char()); /* Get the first character */
- X if ((c == IS_FORWARD) ||
- X (c == IS_REVERSE) ||
- X (c == IS_VMSFORW)) /* Reuse old search string? */
- X {
- X for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */
- X col = echochar(pat[cpos],col); /* and re-echo the string */
- X if (c == IS_REVERSE) { /* forward search? */
- X n = -1; /* No, search in reverse */
- X backchar (TRUE, 1); /* Be defensive about EOB */
- X } else
- X n = 1; /* Yes, search forward */
- X status = scanmore(pat, n); /* Do the search */
- X c = ectoc(expc = get_char()); /* Get another character */
- X }
- X
- X /* Top of the per character loop */
- X
- X for (;;) /* ISearch per character loop */
- X {
- X /* Check for special characters first: */
- X /* Most cases here change the search */
- X
- X if (expc == metac) /* Want to quit searching? */
- X return (TRUE); /* Quit searching now */
- X
- X switch (c) /* dispatch on the input char */
- X {
- X case IS_ABORT: /* If abort search request */
- X return(FALSE); /* Quit searching again */
- X
- X case IS_REVERSE: /* If backward search */
- X case IS_FORWARD: /* If forward search */
- X case IS_VMSFORW: /* of either flavor */
- X if (c == IS_REVERSE) /* If reverse search */
- X n = -1; /* Set the reverse direction */
- X else /* Otherwise, */
- X n = 1; /* go forward */
- X status = scanmore(pat, n); /* Start the search again */
- X c = ectoc(expc = get_char()); /* Get the next char */
- X continue; /* Go continue with the search*/
- X
- X case IS_NEWLINE: /* Carriage return */
- X c = '\n'; /* Make it a new line */
- X break; /* Make sure we use it */
- X
- X case IS_QUOTE: /* Quote character */
- X case IS_VMSQUOTE: /* of either variety */
- X c = ectoc(expc = get_char()); /* Get the next char */
- X
- X case IS_TAB: /* Generically allowed */
- X case '\n': /* controlled characters */
- X break; /* Make sure we use it */
- X
- X case IS_BACKSP: /* If a backspace: */
- X case IS_RUBOUT: /* or if a Rubout: */
- X if (cmd_offset <= 1) /* Anything to delete? */
- X return (TRUE); /* No, just exit */
- X --cmd_offset; /* Back up over the Rubout */
- X cmd_buff[--cmd_offset] = '\0'; /* Yes, delete last char */
- X curwp->w_dotp = curline; /* Reset the line pointer */
- X curwp->w_doto = curoff; /* and the offset */
- X n = init_direction; /* Reset the search direction */
- X strncpy (pat, pat_save, NPAT); /* Restore the old search str */
- X cmd_reexecute = 0; /* Start the whole mess over */
- X goto start_over; /* Let it take care of itself */
- X
- X /* Presumably a quasi-normal character comes here */
- X
- X default: /* All other chars */
- X if (c < ' ') /* Is it printable? */
- X { /* Nope. */
- X reeat (c); /* Re-eat the char */
- X return (TRUE); /* And return the last status */
- X }
- X } /* Switch */
- X
- X /* I guess we got something to search for, so search for it */
- X
- X pat[cpos++] = c; /* put the char in the buffer */
- X if (cpos >= NPAT) /* too many chars in string? */
- X { /* Yup. Complain about it */
- X mlwrite("? Search string too long");
- X return(TRUE); /* Return an error */
- X }
- X pat[cpos] = 0; /* null terminate the buffer */
- X col = echochar(c,col); /* Echo the character */
- X if (!status) { /* If we lost last time */
- X TTputc(BELL); /* Feep again */
- X TTflush(); /* see that the feep feeps */
- X } else /* Otherwise, we must have won*/
- X if (!(status = checknext(c, pat, n))) /* See if match */
- X status = scanmore(pat, n); /* or find the next match */
- X c = ectoc(expc = get_char()); /* Get the next char */
- X } /* for {;;} */
- X}
- X
- X/*
- X * Trivial routine to insure that the next character in the search string is
- X * still true to whatever we're pointing to in the buffer. This routine will
- X * not attempt to move the "point" if the match fails, although it will
- X * implicitly move the "point" if we're forward searching, and find a match,
- X * since that's the way forward isearch works.
- X *
- X * If the compare fails, we return FALSE and assume the caller will call
- X * scanmore or something.
- X */
- X
- Xint checknext (chr, patrn, dir) /* Check next character in search string */
- Xchar chr; /* Next char to look for */
- Xchar *patrn; /* The entire search string (incl chr) */
- Xint dir; /* Search direction */
- X{
- X register LINE *curline; /* current line during scan */
- X register int curoff; /* position within current line */
- X register int buffchar; /* character at current position */
- X int status; /* how well things go */
- X
- X
- X /* setup the local scan pointer to current "." */
- X
- X curline = curwp->w_dotp; /* Get the current line structure */
- X curoff = curwp->w_doto; /* Get the offset within that line */
- X
- X if (dir > 0) /* If searching forward */
- X {
- X if (curoff == llength(curline)) /* If at end of line */
- X {
- X curline = lforw(curline); /* Skip to the next line */
- X if (curline == curbp->b_linep)
- X return (FALSE); /* Abort if at end of buffer */
- X curoff = 0; /* Start at the beginning of the line */
- X buffchar = '\n'; /* And say the next char is NL */
- X } else
- X buffchar = lgetc(curline, curoff++); /* Get the next char */
- X if (status = eq(buffchar, chr)) /* Is it what we're looking for? */
- X {
- X curwp->w_dotp = curline; /* Yes, set the buffer's point */
- X curwp->w_doto = curoff; /* to the matched character */
- X curwp->w_flag |= WFMOVE; /* Say that we've moved */
- X }
- X return (status); /* And return the status */
- X } else /* Else, if reverse search: */
- X return (match_pat (patrn)); /* See if we're in the right place */
- X}
- X
- X/*
- X * This hack will search for the next occurrence of <pat> in the buffer, either
- X * forward or backward. It is called with the status of the prior search
- X * attempt, so that it knows not to bother if it didn't work last time. If
- X * we can't find any more matches, "point" is left where it was before. If
- X * we do find a match, "point" will be at the end of the matched string for
- X * forward searches and at the beginning of the matched string for reverse
- X * searches.
- X */
- X
- Xint scanmore(patrn, dir) /* search forward or back for a pattern */
- Xchar *patrn; /* string to scan for */
- Xint dir; /* direction to search */
- X{
- X int sts; /* search status */
- X
- X if (dir < 0) /* reverse search? */
- X {
- X rvstrcpy(tap, patrn); /* Put reversed string in tap */
- X sts = scanner(tap, REVERSE, PTBEG);
- X }
- X else
- X sts = scanner(patrn, FORWARD, PTEND); /* Nope. Go forward */
- X
- X if (!sts)
- X {
- X TTputc(BELL); /* Feep if search fails */
- X TTflush(); /* see that the feep feeps */
- X }
- X
- X return(sts); /* else, don't even try */
- X}
- X
- X/*
- X * The following is a worker subroutine used by the reverse search. It
- X * compares the pattern string with the characters at "." for equality. If
- X * any characters mismatch, it will return FALSE.
- X *
- X * This isn't used for forward searches, because forward searches leave "."
- X * at the end of the search string (instead of in front), so all that needs to
- X * be done is match the last char input.
- X */
- X
- Xint match_pat (patrn) /* See if the pattern string matches string at "." */
- Xchar *patrn; /* String to match to buffer */
- X{
- X register int i; /* Generic loop index/offset */
- X register int buffchar; /* character at current position */
- X register LINE *curline; /* current line during scan */
- X register int curoff; /* position within current line */
- X
- X /* setup the local scan pointer to current "." */
- X
- X curline = curwp->w_dotp; /* Get the current line structure */
- X curoff = curwp->w_doto; /* Get the offset within that line */
- X
- X /* top of per character compare loop: */
- X
- X for (i = 0; i < strlen(patrn); i++) /* Loop for all characters in patrn */
- X {
- X if (curoff == llength(curline)) /* If at end of line */
- X {
- X curline = lforw(curline); /* Skip to the next line */
- X curoff = 0; /* Start at the beginning of the line */
- X if (curline == curbp->b_linep)
- X return (FALSE); /* Abort if at end of buffer */
- X buffchar = '\n'; /* And say the next char is NL */
- X } else
- X buffchar = lgetc(curline, curoff++); /* Get the next char */
- X if (!eq(buffchar, patrn[i])) /* Is it what we're looking for? */
- X return (FALSE); /* Nope, just punt it then */
- X }
- X return (TRUE); /* Everything matched? Let's celebrate*/
- X}
- X
- X/* Routine to prompt for I-Search string. */
- X
- Xint promptpattern(prompt)
- Xchar *prompt;
- X{
- X char tpat[NPAT+20];
- X
- X strcpy(tpat, prompt); /* copy prompt to output string */
- X strcat(tpat, " ["); /* build new prompt string */
- X expandp(pat, &tpat[strlen(tpat)], NPAT/2); /* add old pattern */
- X strcat(tpat, "]<META>: ");
- X
- X /* check to see if we are executing a command line */
- X if (!clexec) {
- X mlwrite(tpat);
- X }
- X return(strlen(tpat));
- X}
- X
- X/* routine to echo i-search characters */
- X
- Xint echochar(c,col)
- Xint c; /* character to be echoed */
- Xint col; /* column to be echoed in */
- X{
- X movecursor(term.t_nrow,col); /* Position the cursor */
- X if ((c < ' ') || (c == 0x7F)) /* Control character? */
- X {
- X switch (c) /* Yes, dispatch special cases*/
- X {
- X case '\n': /* Newline */
- X TTputc('<');
- X TTputc('N');
- X TTputc('L');
- X TTputc('>');
- X col += 3;
- X break;
- X
- X case '\t': /* Tab */
- X TTputc('<');
- X TTputc('T');
- X TTputc('A');
- X TTputc('B');
- X TTputc('>');
- X col += 4;
- X break;
- X
- X case 0x7F: /* Rubout: */
- X TTputc('^'); /* Output a funny looking */
- X TTputc('?'); /* indication of Rubout */
- X col++; /* Count the extra char */
- X break;
- X
- X default: /* Vanilla control char */
- X TTputc('^'); /* Yes, output prefix */
- X TTputc(c+0x40); /* Make it "^X" */
- X col++; /* Count this char */
- X }
- X } else
- X TTputc(c); /* Otherwise, output raw char */
- X TTflush(); /* Flush the output */
- X return(++col); /* return the new column no */
- X}
- X
- X/*
- X * Routine to get the next character from the input stream. If we're reading
- X * from the real terminal, force a screen update before we get the char.
- X * Otherwise, we must be re-executing the command string, so just return the
- X * next character.
- X */
- X
- Xint get_char ()
- X{
- X int c; /* A place to get a character */
- X
- X /* See if we're re-executing: */
- X
- X if (cmd_reexecute >= 0) /* Is there an offset? */
- X if ((c = cmd_buff[cmd_reexecute++]) != 0)
- X return (c); /* Yes, return any character */
- X
- X /* We're not re-executing (or aren't any more). Try for a real char */
- X
- X cmd_reexecute = -1; /* Say we're in real mode again */
- X update(FALSE); /* Pretty up the screen */
- X if (cmd_offset >= CMDBUFLEN-1) /* If we're getting too big ... */
- X {
- X mlwrite ("? command too long"); /* Complain loudly and bitterly */
- X return (metac); /* And force a quit */
- X }
- X c = get1key(); /* Get the next character */
- X cmd_buff[cmd_offset++] = c; /* Save the char for next time */
- X cmd_buff[cmd_offset] = '\0';/* And terminate the buffer */
- X return (c); /* Return the character */
- X}
- X
- X/*
- X * Hacky routine to re-eat a character. This will save the character to be
- X * re-eaten by redirecting the input call to a routine here. Hack, etc.
- X */
- X
- X/* Come here on the next term.t_getchar call: */
- X
- Xint uneat()
- X{
- X int c;
- X
- X term.t_getchar = saved_get_char; /* restore the routine address */
- X c = eaten_char; /* Get the re-eaten char */
- X eaten_char = -1; /* Clear the old char */
- X return(c); /* and return the last char */
- X}
- X
- Xint reeat(c)
- Xint c;
- X{
- X if (eaten_char != -1) /* If we've already been here */
- X return (NULL); /* Don't do it again */
- X eaten_char = c; /* Else, save the char for later */
- X saved_get_char = term.t_getchar; /* Save the char get routine */
- X term.t_getchar = uneat; /* Replace it with ours */
- X}
- X#else
- Xisearch()
- X{
- X}
- X#endif
- END_OF_isearch.c
- if test 18764 -ne `wc -c <isearch.c`; then
- echo shar: \"isearch.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 9 \(of 14\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- echo "See the readme file"
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-